/*****************************************************************************************
This file is a part of Arise library.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

Arise Engine		Font.cpp

					E-mail:		arise_engine@mail.ru

					Origin by:	Haaf's Game Engine 1.5, 
								Copyright (c) 2003-2004 Relish Games
								http://hge.relishgames.com

created:			02.05.2008
last changes:		05.08.2008
*****************************************************************************************/
#include "stdafx.h"


Font::Font()
{
	fHeight=0.0f;
	fScale=1.0f;
	fRot=0.0f;
	fTracking=0.0f;
	fSpacing=1.0f;

	fZ=0.5f;
	nBlend=BLEND_COLORMUL;
	dwCol=0xFFFFFFFF;

	ZeroMemory( &letters, sizeof(letters) );
	ZeroMemory( &pre, sizeof(letters) );
	ZeroMemory( &post, sizeof(letters) );
}

Font::Font(const Font &fnt)
{
	int i;

	fHeight=fnt.fHeight;
	fScale=fnt.fScale;
	fRot=fnt.fRot;
	fTracking=fnt.fTracking;
	fSpacing=fnt.fSpacing;
	dwCol=fnt.dwCol;
	fZ=fnt.fZ;
	nBlend=fnt.nBlend;

	for(i=0; i<256; i++)
	{
		if(fnt.letters[i]) letters[i]=new Sprite(*fnt.letters[i]);
		else letters[i]=0;
		pre[i]=fnt.pre[i];
		post[i]=fnt.post[i];
	}
}

Font& Font::operator= (const Font &fnt)
{
	int i;
	
	if(this!=&fnt)
	{
		fHeight=fnt.fHeight;
		fScale=fnt.fScale;
		fRot=fnt.fRot;
		fTracking=fnt.fTracking;
		fSpacing=fnt.fSpacing;
		dwCol=fnt.dwCol;
		fZ=fnt.fZ;
		nBlend=fnt.nBlend;

		for(i=0; i<256; i++)
		{
			if(letters[i]) delete letters[i];
			if(fnt.letters[i]) letters[i]=new Sprite(*fnt.letters[i]);
			else letters[i]=0;
			pre[i]=fnt.pre[i];
			post[i]=fnt.post[i];
		}
	}

	return *this;
}

Font::~Font()
{
	for(int i=0; i<256; i++)
	{
		if(letters[i])
		{
			letters[i]->Release();
			delete letters[i];
		}
	}
}

void Font::Render(float x, float y, int align, const char *string)
{
	int i;
	float	fx=x;

	align &= ALIGN_TEXT_HORZMASK;
	if(align==ALIGN_TEXT_RIGHT) fx-=GetStringWidth(string);
	if(align==ALIGN_TEXT_CENTER) fx-=int(GetStringWidth(string)/2.0f);

	while(*string)
	{
		if(*string=='\n')
		{
			y+=int(fHeight*fScale*fSpacing);
			fx=x;
			if(align==ALIGN_TEXT_RIGHT) fx-=GetStringWidth(string+1);
			if(align==ALIGN_TEXT_CENTER) fx-=int(GetStringWidth(string+1)/2.0f);
		}
		else
		{
			i=(unsigned char)*string;
			if(!letters[i]) i='?';
			if(letters[i])
			{
				fx+=pre[i]*fScale;
				letters[i]->RenderEx(fx, y, fRot, fScale);
				fx+=(letters[i]->GetWidth()+post[i]+fTracking)*fScale;
			}
		}
		string++;
	}
}

void Font::printf(float x, float y, int align, const char *format, ...)
{
	char	*pArg=(char *) &format+sizeof(format);
	vsprintf(buffer, format, pArg);

	Render(x,y,align,buffer);
}

void Font::printfb(float x, float y, float w, float h, int align, const char *format, ...)
{
	char	chr, *pbuf, *prevword, *linestart;
	int		i,lines=0;
	float	tx, ty, hh, ww;
	char	*pArg=(char *) &format+sizeof(format);

	vsprintf(buffer, format, pArg);
	linestart=buffer;
	pbuf=buffer;
	prevword=0;

	for(;;)
	{
		i=0;
		while(pbuf[i] && pbuf[i]!=' ' && pbuf[i]!='\n') i++;

		chr=pbuf[i];
		pbuf[i]=0;
		ww=GetStringWidth(linestart);
		pbuf[i]=chr;

		if(ww > w)
		{
			if(pbuf==linestart)
			{
				pbuf[i]='\n';
				linestart=&pbuf[i+1];
			}
			else
			{
				*prevword='\n';
				linestart=prevword+1;
			}

			lines++;
		}

		if(pbuf[i]=='\n')
		{
			prevword=&pbuf[i];
			linestart=&pbuf[i+1];
			pbuf=&pbuf[i+1];
			lines++;
			continue;
		}

		if(!pbuf[i]) {lines++;break;}

		prevword=&pbuf[i];
		pbuf=&pbuf[i+1];
	}
	
	tx=x;
	ty=y;
	hh=fHeight*fSpacing*fScale*lines;

	switch(align & ALIGN_TEXT_HORZMASK)
	{
		case ALIGN_TEXT_LEFT: break;
		case ALIGN_TEXT_RIGHT: tx+=w; break;
		case ALIGN_TEXT_CENTER: tx+=int(w/2); break;
	}

	switch(align & ALIGN_TEXT_VERTMASK)
	{
		case ALIGN_TEXT_TOP: break;
		case ALIGN_TEXT_BOTTOM: ty+=h-hh; break;
		case ALIGN_TEXT_MIDDLE: ty+=int((h-hh)/2); break;
	}

	Render(tx,ty,align,buffer);
}

float Font::GetStringWidth(const char *string) const
{
	int i;
	float w=0;

	while(*string && *string!='\n')
	{
		i=(unsigned char)*string;
		if(!letters[i]) i='?';
		if(letters[i]) w+=letters[i]->GetWidth()+pre[i]+post[i]+fTracking;
		string++;
	}

	return w*fScale;
}

void Font::SetColor(DWORD col)
{
	dwCol=col;
	for(int i=0;i<256;i++) if(letters[i]) letters[i]->SetColor(col);
}

void Font::SetZ(float z)
{
	fZ=z;
	//for(int i=0;i<256;i++) if(letters[i]) letters[i]->SetZ(z);
}

void Font::SetBlendMode(int blend)
{
	nBlend=blend;
	for(int i=0;i<256;i++) if(letters[i]) letters[i]->SetBlendMode(blend);
}
